#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using starLiGHT.Physic.TwoD;
using starLiGHT.Input;
using starLiGHT.Sandbox.Physic2D;

#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif

#endregion

#region LICENSE

/*
    * This file is part of starLiGHT.Collision.
    * Copyright (c) 2007-2010 Roland Rosenkranz http://www.starLiGHT-Engine.de

    * This software is provided 'as-is', without any express or implied
    * warranty.  In no event will the authors be held liable for any damages
    * arising from the use of this software.
    * Permission is granted to anyone to use this software for any purpose,
    * including commercial applications, and to alter it and redistribute it
    * freely, subject to the following restrictions:
    * 1. The origin of this software must not be misrepresented; you must not
    * claim that you wrote the original software. If you use this software
    * in a product, an acknowledgment in the product documentation would be
    * appreciated but is not required.
    * 2. Altered source versions must be plainly marked as such, and must not be
    * misrepresented as being the original software.
    * 3. This notice may not be removed or altered from any source distribution.
    
    * ADDITIONAL (commercial) LICENSES for starLiGHT.Collision are available on request.
*/

#endregion

namespace TestBed
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont spriteFont;
        Settings settings;
        InputManager inputManager;
        Test test;

//TODO: enable the next two lines after making starLiGHT.Components Open Source
//        static SamplingProfiler updateProfiler = new SamplingProfiler("Update");
//        static SamplingProfiler drawTestProfiler = new SamplingProfiler("DrawTest");

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            TestFactory.SingleTest = null;
        }

        public Game1(String testName)
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            if (String.IsNullOrEmpty(testName) || testName.Equals("all", StringComparison.InvariantCultureIgnoreCase))
            {
                TestFactory.SingleTest = null;
            }
            else
            {
                TestFactory.SingleTest = testName;
            }
        }

        protected override void Initialize()
        {
            inputManager = new InputManager(this);
            this.Services.AddService(typeof(InputManager), inputManager);
            this.Components.Add(inputManager);

            InitializeInput();

            test = TestFactory.getActTest(this);
            test.Initialize(this, GraphicsDevice);

            settings = new Settings();
            settings.drawShapes = 1;
            settings.drawStats = 1;
            //settings.drawAABBs = 1;
            //settings.drawContactPoints = 1;
            //settings.drawJoints = 1;

            base.Initialize();
        }

        private void InitializeInput()
        {
            TriggerAction ta;

            ta = inputManager.createAction("EXIT", typeof(TriggerAction)) as TriggerAction;

#if !WINDOWS_PHONE
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Escape, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Back, LogicalPlayerIndex.One));

            ta = inputManager.createAction("RESET", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.R, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Start, LogicalPlayerIndex.One));

            ta = inputManager.createAction("NEXT_TEST", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Add, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.RightShoulder, LogicalPlayerIndex.One));

            ta = inputManager.createAction("PREV_TEST", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.Subtract, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.LeftShoulder, LogicalPlayerIndex.One));

            //
            // ApplyForces test
            //
            ta = inputManager.createAction("STEER_LEFT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.A, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadLeft, LogicalPlayerIndex.One));

            ta = inputManager.createAction("STEER_RIGHT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.D, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadRight, LogicalPlayerIndex.One));

            ta = inputManager.createAction("STEER_FRONT", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.W, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadUp, LogicalPlayerIndex.One));

            ta = inputManager.createAction("STEER_BACK", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.S, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.DPadDown, LogicalPlayerIndex.One));

            //
            // Body-Types test
            //
            ta = inputManager.createAction("BODY_CREATE_DYNAMIC", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.D, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.B, LogicalPlayerIndex.One));

            ta = inputManager.createAction("BODY_CREATE_STATIC", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.S, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.A, LogicalPlayerIndex.One));

            ta = inputManager.createAction("BODY_CREATE_KINEMATIC", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.K, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.Y, LogicalPlayerIndex.One));

            //
            // Confined test
            //
            ta = inputManager.createAction("BODY_CREATE_CIRCLE", typeof(TriggerAction)) as TriggerAction;
            ta.AddDigitalControl(inputManager.GetInputDevice(Keys.C, LogicalPlayerIndex.One));
            ta.AddDigitalControl(inputManager.GetInputDevice(Buttons.A, LogicalPlayerIndex.One));
#else
            TouchPanel.EnabledGestures = GestureType.Flick | GestureType.DoubleTap;

            IDigitalControl back = inputManager.GetInputDevice(PhoneButtons.Back, LogicalPlayerIndex.One);
            ta.AddDigitalControl(back);

#endif
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            spriteFont = Content.Load<SpriteFont>("Arial14");

//TODO: re-enable the SamplingProfiler after making starLiGHT.Components Open Source
//            SamplingProfilerComponent profiler = new SamplingProfilerComponent(this, false, 1.0);
//            profiler.Font = spriteFont;
//            profiler.RenderOverlay = true;
//            profiler.RenderStyle = ProfilerRenderStyle.Graph;
//            profiler.OutputTrace = false;
//            profiler.Offset = new Vector2(GraphicsDevice.Viewport.TitleSafeArea.Left,
//                                          GraphicsDevice.Viewport.TitleSafeArea.Top + 100);
//            Components.Add(profiler);
        }

        protected override void Update(GameTime gameTime)
        {
            //using (new SamplingProfilerMarker(updateProfiler))
            //{
                if (inputManager.IsActionPress("EXIT")) this.Exit();

                if (inputManager.IsActionPress("RESET"))
                {
                    test = TestFactory.getActTest(this);
                    test.Initialize(this, GraphicsDevice);
                }

                if (inputManager.IsActionPress("NEXT_TEST"))
                {
                    test = TestFactory.getNextTest(this);
                    test.Initialize(this, GraphicsDevice);
                }

                if (inputManager.IsActionPress("PREV_TEST"))
                {
                    test = TestFactory.getPreviousTest(this);
                    test.Initialize(this, GraphicsDevice);
                }

#if WINDOWS_PHONE
                while (TouchPanel.IsGestureAvailable)
                {
                    GestureSample gesture = TouchPanel.ReadGesture();

                    if (gesture.GestureType == GestureType.DoubleTap)
                    {
                        // reset the test
                        test = TestFactory.getActTest(this);
                        test.Initialize(this, GraphicsDevice);
                    }
                    else if (gesture.GestureType == GestureType.Flick)
                    {
                        if (gesture.Delta.X < 0)
                            test = TestFactory.getNextTest(this);
                        else
                            test = TestFactory.getPreviousTest(this);

                        test.Initialize(this, GraphicsDevice);
                    }
                }
#endif

                test.Step(GraphicsDevice, settings);

                base.Update(gameTime);
            //}
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            //using (new SamplingProfilerMarker(drawTestProfiler))
            //{
                spriteBatch.Begin();
                test.Draw(settings, spriteBatch, spriteFont);
                spriteBatch.End();
            //}

            base.Draw(gameTime);
        }
    }
}
